#include "dkglCamera.h"
#include "dkglLog.h"

#include <math.h>


namespace DKGL
{
   
#if 1
    Camera::Camera(const String& name) :
        Movable(name),
        _enable(true), 
	    _viewport(NULL),
        _projectionMode(PERSPECTIVE),
	    _orthoWidth(50.0f), _orthoHeight(50.0f),
        _nearPlane(.1f), _farPlane(10000.0f),
        _fov(45.0f)
    {
    }


    Camera::~Camera()
    {
    }


    void Camera::look()
    {
        // check viewport.
	    assert(_viewport&&"Camera does not have a valid viewport");
	
	    float m[16], m2[16];
	
	    // draw viewport boader
	    _viewport->drawBoarder();

	    //viewvolume->setProjection();
	
	    glMatrixMode(GL_PROJECTION);
	    glLoadIdentity();

	    glViewport(_viewport->x, _viewport->y, 
		    (GLsizei)_viewport->width, (GLsizei)_viewport->height);
	
	    if(_projectionMode==PERSPECTIVE)
	    {
		    dbRect2D rc;
		    _calculateOrthoParams(rc);
		    glFrustum(-rc.width/2, rc.width/2, -rc.height/2, rc.height/2, 
			    _nearPlane, _farPlane);
	    }
	    else
	    {
		    float w = (_orthoHeight*_viewport->mAspectRatio)/2;
		    float h = _orthoHeight/2;			
		    glOrtho(-w, w, -h, h, _nearPlane, _farPlane);
	    }

	    // set modelview
	    glMatrixMode(GL_MODELVIEW);
	    if(_parent)
	    {
		    _parent->getParentTransformation(m);
		    glLoadMatrixf(m);
	    }
	    else
	    {
		    glLoadIdentity();
	    }

	    // multi current matrix
	    glMultMatrixf(_localMatrix);

	    glGetFloatv(GL_MODELVIEW_MATRIX, m);

	    ToCameraMatrix(m2, m);
	    glLoadMatrixf(m2);
    }//Endof Look

    void Camera::addChild(MovablePtr)
    {
        throw std::logic_error("Camera can not have any child");
    }


    void Camera::_calculateOrthoParams(dbRect2D& out)
    {
	    out.height = _nearPlane*tan(Degree2Radian(_fov/2.0f))*2.0f;
	    out.width = out.height*_viewport->mAspectRatio;
    }

#else
    //////////////////////////////////////////////////////////////////////////

using namespace std;

Camera::Camera(const string& name) : BaseObject(name) , mEnable(true), 
	mViewport(0), mProjMode(PERSPECTIVE),
	orthoWidth(50.0f), orthoHeight(50.0f)
{
	mNearClipPlane = 0.1;
	mFarClipPlane = 100000.0;
	mFov = 45.0;
}

void Camera::pushChild(BaseObject *p)
{
	Log::dump("Camera can't attach any child entity. ");
}

void Camera::_calculateOrthoParams(dbRect2D& out)
{
	out.height = mNearClipPlane*tan(Degree2Radian(mFov/2.0))*2;
	out.width = out.height*mViewport->mAspectRatio;
}

void Camera::look()
{
	// check viewport.
	assert(mViewport&&"Camera does not have a valid viewport");
	
	float m[16], m2[16];
	
	// draw viewport boader
	mViewport->drawBoarder();

	//viewvolume->setProjection();
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glViewport(mViewport->x, mViewport->y, 
		(GLsizei)mViewport->width, (GLsizei)mViewport->height);
	
	if(mProjMode==PERSPECTIVE)
	{
		dbRect2D rc;
		_calculateOrthoParams(rc);
		//glFrustum(-rc.width/2, rc.width/2, -rc.height/2, rc.height/2, 
			//mNearClipPlane, mFarClipPlane);

		gluPerspective(mFov, mViewport->mAspectRatio, mNearClipPlane, mFarClipPlane);
	}
	else
	{
		float w = (orthoHeight*mViewport->mAspectRatio)/2;
		float h = orthoHeight/2;			
		glOrtho(-w, w, -h, h, mNearClipPlane, mFarClipPlane);
	}

	// set modelview
	glMatrixMode(GL_MODELVIEW);
	if(mParent)
	{
		mParent->getParentTransformation(m);
		glLoadMatrixf(m);
	}
	else
	{
		glLoadIdentity();
	}

	// multi current matrix
	glMultMatrixf(mLocalMatrix);

	glGetFloatv(GL_MODELVIEW_MATRIX, m);

	ToCameraMatrix(m2, m);
	glLoadMatrixf(m2);
}

void Camera::look(const Viewport& vp, bool draw_boarder)
{
	float m2[16], m[16];
	
	// draw viewport boader
	if(draw_boarder)
		vp.drawBoarder();
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glViewport(vp.x, vp.y, 
		(GLsizei)vp.width, (GLsizei)vp.height);
	gluPerspective(mFov, vp.mAspectRatio, mNearClipPlane, mFarClipPlane);

	// set modelview
	glMatrixMode(GL_MODELVIEW);
	if(mParent)
	{
		mParent->getParentTransformation(m);
		glLoadMatrixf(m);
	}
	else
	{
		glLoadIdentity();
	}

	// multi current matrix
	glMultMatrixf(mLocalMatrix);

	glGetFloatv(GL_MODELVIEW_MATRIX, m);

	ToCameraMatrix(m2, m);
	glLoadMatrixf(m2);
}

#endif

}// namespace DKGL